package com.redepronik.negosysdis.invfac.controller;

import static com.redepronik.negosys.utils.Utils.newBigDecimal;

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.primefaces.context.RequestContext;
import org.primefaces.event.SelectEvent;
import org.primefaces.event.UnselectEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.redepronik.negosys.invfac.entity.Banco;
import com.redepronik.negosys.invfac.entity.Egreso;
import com.redepronik.negosys.invfac.entity.Pagoentrada;
import com.redepronik.negosys.invfac.entity.Tipopago;
import com.redepronik.negosys.invfac.entityAux.CobroReporte;
import com.redepronik.negosys.invfac.service.EgresoService;
import com.redepronik.negosys.invfac.service.PagoEntradaService;
import com.redepronik.negosys.invfac.service.TipoPagoService;
import com.redepronik.negosys.rrhh.entity.Persona;
import com.redepronik.negosys.rrhh.service.ClienteService;

@Controller
@Scope("session")
public class CobroBean implements Serializable {

	private static final long serialVersionUID = 1L;

	@Autowired
	private ClienteService clienteService;

	@Autowired
	private TipoPagoService tipoPagoService;

	@Autowired
	private EgresoService egresoService;

	@Autowired
	private PagoEntradaService pagoEntradaService;

	private List<CobroReporte> listaEgresos;
	private List<CobroReporte> listaEgresosSeleccionados;
	private List<Tipopago> listTiposPago;

	private Persona criterioBusquedaCliente;
	private Date criterioBusquedafechaInicio;
	private Date criterioBusquedafechaFin;
	private String criterioBusquedaDocumento;

	private String auxCriterioBusquedaCliente;
	private Date auxCriterioBusquedafechaInicio;
	private Date auxCriterioBusquedafechaFin;
	private String auxCriterioBusquedaDocumento;

	private boolean bn;

	private boolean bnBanco;
	private boolean bnEfectivo;
	private boolean bnTarjeta;
	private String chequeTarjetaVaucher;
	private String chequeTarjetaCuenta;
	private Tipopago tiposPago;
	private CobroReporte cobroReporte;

	private Egreso egreso;
	private List<Pagoentrada> listaPagoEntrada;
	private Pagoentrada pagoEntrada;
	private Banco banco;
	private Date fechapago;
	private BigDecimal totalCuota;
	private BigDecimal totalTotal;

	private BigDecimal totalAbonos;
	private BigDecimal totalSaldo;

	// Cuadro de Busqueda de clientes
	private List<Persona> listaClienteBusqueda;

	private String criterioClienteBusqueda;

	public CobroBean() {
		listaEgresos = new ArrayList<CobroReporte>();
		banco = new Banco();
		bnBanco = false;
		bnEfectivo = false;
		bnTarjeta = false;
		tiposPago = new Tipopago();
		listTiposPago = new ArrayList<Tipopago>();
		listaPagoEntrada = new ArrayList<Pagoentrada>();
		pagoEntrada = new Pagoentrada();
		totalCuota = newBigDecimal();
		totalTotal = newBigDecimal();
		totalSaldo = newBigDecimal();
		totalAbonos = newBigDecimal();
		egreso = new Egreso();
		cobroReporte = new CobroReporte();

		criterioBusquedaCliente = new Persona();
		criterioBusquedafechaInicio = null;
		criterioBusquedafechaFin = null;
		criterioBusquedaDocumento = new String();
	}

	public void cargarCliente(SelectEvent event) {
		criterioBusquedaCliente = clienteService
				.obtenerPorPersonaId(criterioBusquedaCliente.getPersonaid());
	}

	public void cargarEgreso() {
		egreso = egresoService.obtenerPorCodigo(cobroReporte
				.getCodigoDocumento());
	}

	public void comprobarEgresosSeleccionados() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean error = false;

		if (listaEgresosSeleccionados == null
				|| listaEgresosSeleccionados.isEmpty()) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA", "ESCOJA POR LO MENOS UN REGISTRO"));
			error = true;
		}
		context.addCallbackParam("error1", error ? true : false);
	}

	public void eliminarPagoEntrada() {
		listaPagoEntrada.remove(pagoEntrada);
		totalCuota = totalCuota.subtract(pagoEntrada.getCuota());
	}

	public Banco getBanco() {
		return banco;
	}

	public String getChequeTarjetaCuenta() {
		return chequeTarjetaCuenta;
	}

	public String getChequeTarjetaVaucher() {
		return chequeTarjetaVaucher;
	}

	public CobroReporte getCobroReporte() {
		return cobroReporte;
	}

	public Persona getCriterioBusquedaCliente() {
		return criterioBusquedaCliente;
	}

	public String getCriterioBusquedaDocumento() {
		return criterioBusquedaDocumento;
	}

	public Date getCriterioBusquedafechaFin() {
		return criterioBusquedafechaFin;
	}

	public Date getCriterioBusquedafechaInicio() {
		return criterioBusquedafechaInicio;
	}

	public String getCriterioClienteBusqueda() {
		return criterioClienteBusqueda;
	}

	public Egreso getEgreso() {
		return egreso;
	}

	public Date getFechapago() {
		return fechapago;
	}

	public List<Persona> getListaClienteBusqueda() {
		return listaClienteBusqueda;
	}

	public List<CobroReporte> getListaEgresos() {
		return listaEgresos;
	}

	public List<CobroReporte> getListaEgresosSeleccionados() {
		return listaEgresosSeleccionados;
	}

	public List<Pagoentrada> getListaPagoEntrada() {
		return listaPagoEntrada;
	}

	public List<Tipopago> getListTiposPago() {
		return listTiposPago;
	}

	public Pagoentrada getPagoEntrada() {
		return pagoEntrada;
	}

	public Tipopago getTiposPago() {
		return tiposPago;
	}

	public BigDecimal getTotalAbonos() {
		return totalAbonos;
	}

	public BigDecimal getTotalCuota() {
		return totalCuota;
	}

	public BigDecimal getTotalSaldo() {
		return totalSaldo;
	}

	public BigDecimal getTotalTotal() {
		return totalTotal;
	}

	@PostConstruct
	public void init() {
		bn = true;
		listTiposPago = tipoPagoService.obtener();
		tiposPago.setTipopagoid(1);
		listaEgresosSeleccionados = new ArrayList<CobroReporte>();
	}

	public void insertarCobro() {
		RequestContext context = RequestContext.getCurrentInstance();
		boolean error = false;

		if (listaPagoEntrada == null || listaPagoEntrada.isEmpty()) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA", "INGRESE POR LO MENOS UN PAGO"));
			error = true;
		} else {
			pagoEntradaService.cobro(listaPagoEntrada,
					listaEgresosSeleccionados);
			// cargarCliente(null);
			List<Egreso> lista = egresoService
					.obtenerPorEstado(auxCriterioBusquedaCliente, 9,
							auxCriterioBusquedaDocumento,
							auxCriterioBusquedafechaInicio,
							auxCriterioBusquedafechaFin);
			listaEgresos = new ArrayList<CobroReporte>();
			if (lista == null || lista.isEmpty()) {
				bn = true;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"MENSAJE DEL SISTEMA",
						"EL CLIENTE NO TIENE FACTURAS PENDIENTES"));
				limpiar();
			} else {
				bn = false;

				totalTotal = newBigDecimal();
				totalAbonos = newBigDecimal();
				totalSaldo = newBigDecimal();

				for (Egreso egreso : lista) {
					CobroReporte cobroReporte = new CobroReporte();

					cobroReporte.setId(egreso.getEgresoid());
					cobroReporte.setCliente(egreso.getCliente().getPersona()
							.getApellido()
							+ " "
							+ egreso.getCliente().getPersona().getNombre());
					cobroReporte.setEscogido(false);
					cobroReporte.setOrden(0);
					cobroReporte.setTipoDocumento(egreso.getTipodocumento()
							.getNombre());
					cobroReporte
							.setCodigoDocumento(egreso.getCodigodocumento());
					cobroReporte.setFechaEmision(egreso.getFechainicio());
					cobroReporte.setTotal(egresoService.calcularTotal(egreso));
					cobroReporte.setAbono(egresoService
							.calcularEntradas(egreso));
					cobroReporte.setSaldo(cobroReporte.getTotal().subtract(
							cobroReporte.getAbono()));

					listaEgresos.add(cobroReporte);
				}
			}

			listaPagoEntrada = new ArrayList<Pagoentrada>();
			totalCuota = new BigDecimal("0");
			listaEgresosSeleccionados = new ArrayList<CobroReporte>();
			totalTotal = newBigDecimal();
			totalAbonos = newBigDecimal();
			totalSaldo = newBigDecimal();
		}
		context.addCallbackParam("error", error ? true : false);
	}

	public void insertarPagoEntrada() {
		if (pagoEntrada.getCuota().compareTo(new BigDecimal("0")) == 0) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA", "INGRESE UN MONTO"));
		} else if (fechapago == null) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA", "INGRESE UNA FECHA"));
		} else {
			BigDecimal auxTotalCuota = totalCuota.add(pagoEntrada.getCuota());
			if (auxTotalCuota.compareTo(totalSaldo) > 0) {
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
						"MENSAJE DEL SISTEMA",
						"LA SUMA DE LAS CUOTAS NO DEBE SER MAYOR AL TOTAL DEL SALDO"));
			} else {
				pagoEntrada.setTipopago(tipoPagoService
						.obtenerPorTipoPagoId(tiposPago.getTipopagoid()));
				pagoEntrada.setFechapago(new Timestamp(fechapago.getTime()));

				totalCuota = auxTotalCuota;
				listaPagoEntrada.add(pagoEntrada);

				pagoEntrada = new Pagoentrada();
				tiposPago = new Tipopago();
				fechapago = null;
				bnBanco = false;
				bnEfectivo = false;
				bnTarjeta = false;
				tiposPago.setTipopagoid(1);
			}
		}
	}

	public boolean isBn() {
		return bn;
	}

	public boolean isBnBanco() {
		return bnBanco;
	}

	public boolean isBnEfectivo() {
		return bnEfectivo;
	}

	public boolean isBnTarjeta() {
		return bnTarjeta;
	}

	public void limpiar() {
		listaPagoEntrada = new ArrayList<Pagoentrada>();
		criterioBusquedaCliente = new Persona();
		totalCuota = newBigDecimal();
		totalTotal = newBigDecimal();
		totalSaldo = newBigDecimal();
		totalAbonos = newBigDecimal();
	}

	public void limpiarObjetosBusquedaCliente() {
		criterioClienteBusqueda = new String();
		listaClienteBusqueda = new ArrayList<Persona>();
	}

	public void obtenerClientesPorBusqueda() {
		if (criterioClienteBusqueda.length() >= 0
				&& criterioClienteBusqueda.length() <= 3) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_ERROR,
					"MENSAJE DEL SISTEMA", "INGRESE MAS DE 3 CARACTERES"));
		} else {
			listaClienteBusqueda = clienteService
					.obtener(criterioClienteBusqueda.toUpperCase());
			if (listaClienteBusqueda.isEmpty()) {
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
						"MENSAJE DEL SISTEMA",
						"NO SE ENCONTRO NINGUNA COINCIDENCIA"));
			}
			criterioClienteBusqueda = new String();
		}
	}

	public void obtenerFacturasPendientes() {
		if (criterioBusquedaCliente.getCedula() == null
				&& criterioBusquedafechaInicio == null
				&& criterioBusquedafechaFin == null
				&& (criterioBusquedaDocumento == null || criterioBusquedaDocumento
						.compareTo("") == 0)) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA", "INGRESE ALGÚN CRITERIO DE BÚSQUEDA"));
		} else if (criterioBusquedafechaInicio != null
				&& criterioBusquedafechaFin != null
				&& criterioBusquedafechaInicio.after(criterioBusquedafechaFin)) {
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA",
					"LA FECHA DE INICIO DEBE SER MENOR A LA FECHA FINAL"));
		} else {
			listaEgresos = new ArrayList<CobroReporte>();

			List<Egreso> lista = egresoService.obtenerPorEstado(
					criterioBusquedaCliente.getCedula(), 9,
					criterioBusquedaDocumento, criterioBusquedafechaInicio,
					criterioBusquedafechaFin);

			auxCriterioBusquedaCliente = criterioBusquedaCliente.getCedula();
			auxCriterioBusquedafechaInicio = criterioBusquedafechaInicio;
			auxCriterioBusquedafechaFin = criterioBusquedafechaFin;
			auxCriterioBusquedaDocumento = criterioBusquedaDocumento;

			criterioBusquedaCliente = new Persona();
			criterioBusquedafechaInicio = null;
			criterioBusquedafechaFin = null;
			criterioBusquedaDocumento = new String();

			if (lista == null || lista.isEmpty()) {
				bn = true;
				presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_INFO,
						"MENSAJE DEL SISTEMA", "NO EXISTEN FACTURAS PENDIENTES"));
				limpiar();
			} else {
				bn = false;

				totalTotal = newBigDecimal();
				totalAbonos = newBigDecimal();
				totalSaldo = newBigDecimal();

				for (Egreso egreso : lista) {
					CobroReporte cobroReporte = new CobroReporte();

					cobroReporte.setId(egreso.getEgresoid());
					cobroReporte.setCliente(egreso.getCliente().getPersona()
							.getApellido()
							+ " "
							+ egreso.getCliente().getPersona().getNombre());
					cobroReporte.setEscogido(false);
					cobroReporte.setOrden(0);
					cobroReporte.setTipoDocumento(egreso.getTipodocumento()
							.getNombre());
					cobroReporte
							.setCodigoDocumento(egreso.getCodigodocumento());
					cobroReporte.setFechaEmision(egreso.getFechainicio());
					cobroReporte.setTotal(egresoService.calcularTotal(egreso));
					cobroReporte.setAbono(egresoService
							.calcularEntradas(egreso));
					cobroReporte.setSaldo(cobroReporte.getTotal().subtract(
							cobroReporte.getAbono()));

					listaEgresos.add(cobroReporte);
				}
			}
		}
	}

	public void onRowSelect(SelectEvent event) {
		if (listaEgresosSeleccionados.size() > 1
				&& listaEgresosSeleccionados
						.get(0)
						.getCliente()
						.compareTo(
								listaEgresosSeleccionados.get(
										listaEgresosSeleccionados.size() - 1)
										.getCliente()) != 0) {
			listaEgresosSeleccionados
					.remove(listaEgresosSeleccionados.size() - 1);
			presentaMensaje(new FacesMessage(FacesMessage.SEVERITY_WARN,
					"MENSAJE DEL SISTEMA",
					"SOLO PUEDE ESCOJER FACTURAS DE UN MISMO CLIENTE"));
		}

		totalTotal = newBigDecimal();
		totalAbonos = newBigDecimal();
		totalSaldo = newBigDecimal();
		for (CobroReporte cr : listaEgresosSeleccionados) {
			totalTotal = totalTotal.add(cr.getTotal());
			totalAbonos = totalAbonos.add(cr.getAbono());
			totalSaldo = totalSaldo.add(cr.getSaldo());
		}

		for (CobroReporte cr1 : listaEgresos) {
			cr1.setEscogido(false);
			cr1.setOrden(0);
		}

		int orden = 1;
		for (CobroReporte cr1 : listaEgresosSeleccionados) {
			cr1.setOrden(orden++);
		}

		for (CobroReporte cr1 : listaEgresos) {
			for (CobroReporte cr2 : listaEgresosSeleccionados) {
				if (cr1.getId() == cr2.getId()) {
					cr1.setEscogido(true);
					cr1.setOrden(cr2.getOrden());
					break;
				}
			}
		}
	}

	public void onRowUnselect(UnselectEvent event) {
		System.out.println("entre");
		totalAbonos = newBigDecimal();
		totalSaldo = newBigDecimal();
		for (CobroReporte cr : listaEgresosSeleccionados) {
			totalTotal = totalTotal.add(cr.getTotal());
			totalAbonos = totalAbonos.add(cr.getAbono());
			totalSaldo = totalSaldo.add(cr.getSaldo());
		}

		for (CobroReporte cr1 : listaEgresos) {
			cr1.setEscogido(false);
			cr1.setOrden(0);
		}

		int orden = 1;
		for (CobroReporte cr1 : listaEgresosSeleccionados) {
			cr1.setOrden(orden++);
		}

		for (CobroReporte cr1 : listaEgresos) {
			for (CobroReporte cr2 : listaEgresosSeleccionados) {
				if (cr1.getId() == cr2.getId()) {
					cr1.setEscogido(true);
					cr1.setOrden(cr2.getOrden());
					break;
				}
			}
		}
	}

	private void presentaMensaje(FacesMessage message) {
		FacesContext.getCurrentInstance().addMessage(null, message);
	}

	public void setBanco(Banco banco) {
		this.banco = banco;
	}

	public void setBn(boolean bn) {
		this.bn = bn;
	}

	public void setBnBanco(boolean bnBanco) {
		this.bnBanco = bnBanco;
	}

	public void setBnEfectivo(boolean bnEfectivo) {
		this.bnEfectivo = bnEfectivo;
	}

	public void setBnTarjeta(boolean bnTarjeta) {
		this.bnTarjeta = bnTarjeta;
	}

	public void setChequeTarjetaCuenta(String chequeTarjetaCuenta) {
		this.chequeTarjetaCuenta = chequeTarjetaCuenta;
	}

	public void setChequeTarjetaVaucher(String chequeTarjetaVaucher) {
		this.chequeTarjetaVaucher = chequeTarjetaVaucher;
	}

	public void setCobroReporte(CobroReporte cobroReporte) {
		this.cobroReporte = cobroReporte;
	}

	public void setCriterioBusquedaCliente(Persona criterioBusquedaCliente) {
		this.criterioBusquedaCliente = criterioBusquedaCliente;
	}

	public void setCriterioBusquedaDocumento(String criterioBusquedaDocumento) {
		this.criterioBusquedaDocumento = criterioBusquedaDocumento;
	}

	public void setCriterioBusquedafechaFin(Date criterioBusquedafechaFin) {
		this.criterioBusquedafechaFin = criterioBusquedafechaFin;
	}

	public void setCriterioBusquedafechaInicio(Date criterioBusquedafechaInicio) {
		this.criterioBusquedafechaInicio = criterioBusquedafechaInicio;
	}

	public void setCriterioClienteBusqueda(String criterioClienteBusqueda) {
		this.criterioClienteBusqueda = criterioClienteBusqueda;
	}

	public void setEgreso(Egreso egreso) {
		this.egreso = egreso;
	}

	public void setFechapago(Date fechapago) {
		this.fechapago = fechapago;
	}

	public void setListaClienteBusqueda(List<Persona> listaClienteBusqueda) {
		this.listaClienteBusqueda = listaClienteBusqueda;
	}

	public void setListaEgresos(List<CobroReporte> listaEgresos) {
		this.listaEgresos = listaEgresos;
	}

	public void setListaEgresosSeleccionados(
			List<CobroReporte> listaEgresosSeleccionados) {
		this.listaEgresosSeleccionados = listaEgresosSeleccionados;
	}

	public void setListaPagoEntrada(List<Pagoentrada> listaPagoEntrada) {
		this.listaPagoEntrada = listaPagoEntrada;
	}

	public void setListTiposPago(List<Tipopago> listTiposPago) {
		this.listTiposPago = listTiposPago;
	}

	public void setPagoEntrada(Pagoentrada pagoEntrada) {
		this.pagoEntrada = pagoEntrada;
	}

	public void setTiposPago(Tipopago tiposPago) {
		this.tiposPago = tiposPago;
	}

	public void setTotalAbonos(BigDecimal totalAbonos) {
		this.totalAbonos = totalAbonos;
	}

	public void setTotalCuota(BigDecimal totalCuota) {
		this.totalCuota = totalCuota;
	}

	public void setTotalSaldo(BigDecimal totalSaldo) {
		this.totalSaldo = totalSaldo;
	}

	public void setTotalTotal(BigDecimal totalTotal) {
		this.totalTotal = totalTotal;
	}

	public void tipoPago() {
		if (tiposPago.getTipopagoid() == 1) {
			bnEfectivo = true;
			bnTarjeta = false;
			bnBanco = false;
		} else if (tiposPago.getTipopagoid() == 2) {
			bnEfectivo = false;
			bnTarjeta = true;
			bnBanco = false;
			chequeTarjetaCuenta = "# TARJETA";
			chequeTarjetaVaucher = "# VAUCHER";
		} else if (tiposPago.getTipopagoid() == 3) {
			bnEfectivo = false;
			bnTarjeta = true;
			bnBanco = true;
			chequeTarjetaCuenta = "# CUENTA";
			chequeTarjetaVaucher = "# CHEQUE";
		}
	}

}